const data = {
  text: "hello world",
  ok: true,
};

// const bucket = new Set();
const bucket = new WeakMap();
const obj = new Proxy(data, {
  get(target, key) {
    console.log("get==key==", key);
    track(target, key);
    return target[key];
  },
  set(target, key, val) {
    target[key] = val;
    trigger(target, key);
    return true;
  },
});

let activeEffect = undefined;
const effect = (fn) => {
  activeEffect = fn;
  fn();
};
// 追踪
const track = (target, key) => {
  if (!activeEffect) return;

  let depsMap = bucket.get(target); // WeakMap 由 target --> Map 构成；
  if (!depsMap) {
    bucket.set(target, (depsMap = new Map()));
  }
  let deps = depsMap.get(key); // Map 由 key --> Set 构成
  if (!deps) {
    depsMap.set(key, (deps = new Set()));
  }
  // 最后将当前激活的副作用函数添加到桶中
  deps.add(activeEffect);

  // deps就是一个与当前副作用函数存在关联的依赖集合
  activeEffect.deps.push(deps);
  console.log(888, deps);
  console.log(999, activeEffect.deps);
};
// 触发
const trigger = (target, key) => {
  let depsMap = bucket.get(target);
  if (!depsMap) return;
  let deps = depsMap.get(key);
  // 执行副作用函数
  const effectSet = new Set(deps);
  console.log("trigger==", key, effectSet);
  effectSet && effectSet.forEach((fn) => fn());
};

// effect(() => {
//   console.log("读去元素obj.noExist==", obj.noExist);
// });

// 4.4 分支切换与cleanup
// 每次副作用函数执行时 先把他从所有与之关联的依赖集合中删除
const effect2 = (fn) => {
  const _effectFn = () => {
    cleanup(_effectFn);
    activeEffect = _effectFn;
    console.log("activeEffect==", activeEffect.deps);
    fn();
  };
  //  用来存储 所有与当前副作用函数相关联的依赖集合
  _effectFn.deps = [];

  _effectFn();
};

const cleanup = (effectFn) => {
  for (let i = 0; i < effectFn.deps.length; i++) {
    const deps = effectFn.deps[i];
    deps.delete(effectFn);
  }
  effectFn.deps.length = 0;
};

// 测试代码
// effect(() => {
//   console.log("读去元素obj.text==", obj.ok ? obj.text : "not");
// });
effect2(() => {
  console.log("effect2-1==元素obj.text==", obj.ok ? obj.text : "not");
});
// effect2(() => {
//   console.log("effect2-2=文案==", obj.ok ? "yes" : "no");
// });
setTimeout(() => {
  console.log("2秒之后执行==");
  obj.ok = false;
}, 2000);
setTimeout(() => {
  console.log("3秒之后执行==");
  // 执行之后不会再出发副作用函数的调用
  obj.text = "hello vue3";
}, 3000);
